package com.fastloan.safe.mgt.org.service.impl;

import com.fastloan.safe.core.param.RoleTypeEnum;
import com.fastloan.safe.core.util.ManagerKit;
import com.fastloan.safe.mgt.auth.model.CmuRole;
import com.fastloan.safe.mgt.auth.model.CmuRoleFun;
import com.fastloan.safe.mgt.auth.model.CmuUserFun;
import com.fastloan.safe.mgt.auth.model.CmuUserRole;
import com.fastloan.safe.mgt.auth.service.CmuRoleFunService;
import com.fastloan.safe.mgt.auth.service.CmuRoleService;
import com.fastloan.safe.mgt.auth.service.CmuUserFunService;
import com.fastloan.safe.mgt.auth.service.CmuUserRoleService;
import com.fastloan.safe.mgt.org.dao.CmuOrgMapper;
import com.fastloan.safe.mgt.org.model.CmuOrg;
import com.fastloan.safe.mgt.org.model.CmuOrgUser;
import com.fastloan.safe.mgt.org.model.vo.OrgTreeVo;
import com.fastloan.safe.mgt.org.model.vo.OrgVo;
import com.fastloan.safe.mgt.org.service.CmuOrgService;
import com.fastloan.safe.mgt.org.service.CmuOrgUserService;
import com.fastloan.safe.mgt.root.model.CmDefFun;
import com.fastloan.safe.mgt.root.model.CmDefRole;
import com.fastloan.safe.mgt.root.model.CmDefRoleFun;
import com.fastloan.safe.mgt.root.model.CmuFun;
import com.fastloan.safe.mgt.root.model.vo.DefFunTreeVo;
import com.fastloan.safe.mgt.root.service.CmDefFunService;
import com.fastloan.safe.mgt.root.service.CmDefRoleFunService;
import com.fastloan.safe.mgt.root.service.CmDefRoleService;
import com.fastloan.safe.mgt.root.service.CmFunService;
import com.fastloan.safe.mgt.user.model.CmuUser;
import com.fastloan.safe.mgt.user.service.CmuUserService;
import com.kawins.base.BaseMapper;
import com.kawins.base.baseabs.BaseServiceImpl;
import com.kawins.shiro.temp.util.PasswordUtil;
import com.kawins.supers.file.IFileManager;
import com.kawins.supers.file.core.FileLoadBean;
import com.kawins.supers.table.manager.DataTable;
import com.kawins.supers.tree.Bean2TreeUtil;
import com.kawins.util.colle.ListUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import tk.mybatis.mapper.entity.Example;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.*;

/**
 * @author rankai
 * createTime 2017-09-2017/9/28 11:28
 */
public class CmuOrgServiceImpl extends BaseServiceImpl<CmuOrg> implements CmuOrgService {

    @Autowired
    private CmuOrgMapper orgMapper;

    @Autowired
    private CmDefFunService defFunService;

    @Autowired
    private CmFunService funService;

    @Autowired
    private CmDefRoleService defRoleService;

    @Autowired
    private CmDefRoleFunService defRoleFunService;

    @Autowired
    private CmuRoleService roleService;

    @Autowired
    private CmuOrgService orgService;

    @Autowired
    private CmuUserService userService;

    @Autowired
    private CmuUserRoleService userRoleService;

    @Autowired
    private CmuRoleFunService roleFunService;

    @Autowired
    private CmuOrgUserService orgUserService;

    @Autowired
    private CmuUserFunService userFunService;

    @Autowired
    private IFileManager fileManager;

    private static final NumberFormat ORG_FORMAT = new DecimalFormat("00000000000");

    @Override
    protected BaseMapper<CmuOrg> buildDao() {
        return orgMapper;
    }

    @Override
    @DataTable(name = "cmuOrgPageList")
    public List<OrgVo> pageList(Map<String, Object> map) {
        return orgMapper.pageList(map);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertTopOrg(CmuOrg cmuOrg, CmuUser cmuUser, String[] funIds, MultipartFile logoFile) {
        //上传文件
        FileLoadBean fileLoadBean = fileManager.upload(logoFile);

        //插入机构
        cmuOrg.setParentId(TOP_ORG_PARENT_ID);
        cmuOrg.setCreateTime(new Date());
        cmuOrg.setCreateBy(ManagerKit.getUser().getId());
        cmuOrg.setProfile(fileLoadBean.getFileId().toString());
        insertSelective(cmuOrg);

        //插入功能
        Set<String> funIdsSet = insertFun(cmuOrg, funIds);

        //插入默认角色
        List<CmDefRole> defRoles = defRoleService.select(new CmDefRole().setIsAdmin(0));

        List<String> defFunIds = selectCheckFunWithSon(funIdsSet);

        for (CmDefRole defRole : defRoles) {
            CmuRole cmuRole = new CmuRole().setTopOrgId(cmuOrg.getId()).setName(defRole.getName())
                    .setDescribes(defRole.getDescribes()).setIndexType(defRole.getIndexType())
                    .setStates(1).setIsDef(defRole.getIsDef()).setCreateBy(defRole.getCreateBy());
            roleService.insertSelective(cmuRole);
            List<CmDefRoleFun> defRoleFuns = defRoleFunService.select(new CmDefRoleFun().setDefRoleId(defRole.getId()));
            List<String> list = listRetainAll(defRoleFuns, defFunIds);
            List<CmuRoleFun> roleFunList = new ArrayList<>(list.size());
            for (String funId : list) {
                roleFunList.add(new CmuRoleFun().setDefFunId(funId).setRoleId(cmuRole.getId()));
            }
            if (roleFunList.size() > 0) {
                roleFunService.insertList(roleFunList);
            }
        }

        //插入用户信息
        String uuid = UUID.randomUUID().toString();
        cmuUser.setSalt(uuid);
        cmuUser.setPassword(PasswordUtil.encryptPassword(CmuUserService.DEF_PASSWORD, uuid));
        cmuUser.setCreateTime(new Date());
        cmuUser.setCreateBy(ManagerKit.getUser().getId());
        cmuUser.setStatus(0);
        cmuUser.setRootRoleId(null);
        userService.insertSelective(cmuUser);

        //插入用户角色信息
        CmuRole cmuRole = roleService.selectOne(new CmuRole().setIsDef(1)
                .setIndexType(RoleTypeEnum.ADMIN.getCode()).setTopOrgId(cmuOrg.getId()));
        CmuUserRole userRole = new CmuUserRole().setIsDef(1).setRoleId(cmuRole.getId()).setUserId(cmuUser.getId());
        userRoleService.insertSelective(userRole);

        //插入用户机构信息
        CmuOrgUser orgUser = new CmuOrgUser().setUserId(cmuUser.getId()).setOrgId(cmuOrg.getId());
        orgUserService.insert(orgUser);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateTopOrg(CmuOrg cmuOrg, String[] funIds, MultipartFile logoFile) {
        if (logoFile != null && logoFile.getSize() > 0) {
            CmuOrg org = selectByPrimaryKey(cmuOrg.getId());
            FileLoadBean loadBean = fileManager.update(org.getProfile(), logoFile);
            cmuOrg.setProfile(loadBean.getFileId().toString());
        }
        cmuOrg.setParentId(null);
        cmuOrg.setCreateTime(null);
        cmuOrg.setCreateBy(null);
        updateByPrimaryKeySelective(cmuOrg);
        List<CmuFun> oldFun = funService.select(new CmuFun().setTopOrgId(cmuOrg.getId()));
        funService.delete(new CmuFun().setTopOrgId(cmuOrg.getId()));
        //插入功能
        Set<String> funIdsSet = insertFun(cmuOrg, funIds);
        Set<String> oldSet = new HashSet<>(oldFun.size());
        for (CmuFun fun : oldFun) {
            oldSet.add(fun.getDefFunId());
        }

        oldSet.removeAll(funIdsSet);
        if (oldSet.size() > 0) {
            List<String> defFunIds = selectCheckFunWithSon(oldSet);

            List<CmuRole> cmuRoles = roleService.select(new CmuRole().setTopOrgId(cmuOrg.getId()));
            Set<Object> set = ListUtil.listField2Set("id", cmuRoles);
            Example example = new Example(CmuRoleFun.class);
            example.createCriteria().andIn("roleId", set).andIn("defFunId", defFunIds);
            roleFunService.deleteByExample(example);

            List<OrgTreeVo> orgTreeVos = orgService.selectSonByTop(cmuOrg.getId(), true, false);
            Set<Object> orgIds = ListUtil.listField2Set("id", orgTreeVos);

            example = new Example(CmuOrgUser.class);
            example.createCriteria().andIn("ordId", orgIds);
            List<CmuOrgUser> cmuOrgUsers = orgUserService.selectByExample(example);
            Set<Object> userIds = ListUtil.listField2Set("userId", cmuOrgUsers);
            example = new Example(CmuUserFun.class);
            example.createCriteria().andEqualTo("userId", userIds).andIn("defFunId", defFunIds);
            userFunService.deleteByExample(example);
        }
    }

    private Set<String> insertFun(CmuOrg cmuOrg, String[] funIds) {
        List<String> funIdsList = new ArrayList<>();
        if (funIds != null) {
            funIdsList = Arrays.asList(funIds);
        }
        Set<String> funIdsSet = new HashSet<>(funIdsList);
        List<CmDefFun> select = defFunService.select(new CmDefFun().
                setParentId(CmDefFunService.TOP_FUN_PARENT_ID).setIsAdmin(0).setIsDef(1));
        for (CmDefFun defFun : select) {
            funIdsSet.add(defFun.getId());
        }
        List<CmuFun> cmuFun = new ArrayList<>(funIdsSet.size());
        for (String funId : funIdsSet) {
            cmuFun.add(new CmuFun().setTopOrgId(cmuOrg.getId()).setDefFunId(funId));
        }
        if (cmuFun.size() > 0) {
            funService.insertList(cmuFun);
        }
        return funIdsSet;
    }

    @Override
    public String selectOrgByUser(String userId) {
        CmuOrgUser cmuOrgUser = orgUserService.selectOne(new CmuOrgUser().setUserId(userId));
        return cmuOrgUser.getOrgId();
    }

    @Override
    public List<CmuOrg> selectTopOrgBySon(String orgId, boolean hasSelf, boolean onlyTop) {
        return orgMapper.selectTopOrgBySon(orgId, hasSelf, onlyTop);
    }

    @Override
    public List<OrgTreeVo> selectSonByTop(String orgId, boolean hasSelf, boolean isTree) {
        List<OrgTreeVo> orgTreeVos = orgMapper.selectSonByTop(orgId, hasSelf);
        if (orgTreeVos.size() > 0) {
            if (isTree) {
                Bean2TreeUtil<OrgTreeVo> bean2TreeUtil = new Bean2TreeUtil<>();
                CmuOrg cmuOrg = selectByPrimaryKey(orgId);
                return bean2TreeUtil.getChildNodesByParentId(orgTreeVos, cmuOrg.getParentId());
            }
        }
        return orgTreeVos;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insertSonOrg(CmuOrg cmuOrg, MultipartFile weixinCode, MultipartFile logoFile) {
        FileLoadBean upload = fileManager.upload(logoFile);
        cmuOrg.setProfile(upload.getFileId().toString());
        if (weixinCode != null && weixinCode.getSize() > 0) {
            upload = fileManager.upload(weixinCode);
            cmuOrg.setWeixinCode(upload.getFileId().toString());
        }
        cmuOrg.setCreateBy(ManagerKit.getUserId());
        cmuOrg.setCreateTime(new Date());
        insertSelective(cmuOrg);
        return true;
    }

    @Override
    public boolean insertSonOrg(CmuOrg cmuOrg, MultipartFile... files) {
        cmuOrg.setWeixinCode(getFileId(files[0]));
        cmuOrg.setProfile(getFileId(files[1]));
        cmuOrg.setLicenseImg(getFileId(files[2]));
        cmuOrg.setCreateBy(ManagerKit.getUserId());
        cmuOrg.setOrgCode(ORG_FORMAT.format(orgMapper.selectSequence()));
        cmuOrg.setCreateTime(new Date());
        insertSelective(cmuOrg);
        return true;
    }

    private String getFileId(MultipartFile file) {
        if (file != null && file.getSize() > 0) {
            FileLoadBean upload = fileManager.upload(file);
            return upload.getFileId().toString();
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateSonOrg(CmuOrg cmuOrg, MultipartFile weixinCode, MultipartFile logoFile, MultipartFile licenseImg) {
        CmuOrg org = selectByPrimaryKey(cmuOrg.getId());
        if (logoFile != null && logoFile.getSize() != 0) {
            FileLoadBean update = fileManager.update(org.getProfile(), logoFile);
            cmuOrg.setProfile(update.getFileId().toString());
        }
        if (weixinCode != null && weixinCode.getSize() > 0) {
            FileLoadBean update = fileManager.update(org.getWeixinCode(), weixinCode);
            cmuOrg.setWeixinCode(update.getFileId().toString());
        }
        if (licenseImg != null && licenseImg.getSize() > 0) {
            FileLoadBean update = fileManager.update(org.getWeixinCode(), licenseImg);
            cmuOrg.setLicenseImg(update.getFileId().toString());
        }
        cmuOrg.setParentId(null);
        cmuOrg.setCreateBy(null);
        cmuOrg.setCreateTime(null);
        updateByPrimaryKeySelective(cmuOrg);
        return true;
    }


    private List<String> selectCheckFunWithSon(Set<String> funIdsSet) {
        List<DefFunTreeVo> cmDefFuns = new ArrayList<>(0);
        for (String funId : funIdsSet) {
            cmDefFuns.addAll(defFunService.selectAllSonByTop(funId, true));
        }
        List<String> list = new ArrayList<>(cmDefFuns.size());
        for (DefFunTreeVo cmDefFun : cmDefFuns) {
            list.add(cmDefFun.getId());
        }
        return list;
    }

    private List<String> listRetainAll(List<CmDefRoleFun> defRoleFuns, List<String> cmDefFuns) {
        List<String> defFunIds = new ArrayList<>(defRoleFuns.size());
        for (CmDefRoleFun defRoleFun : defRoleFuns) {
            defFunIds.add(defRoleFun.getDefFunId());
        }
        defFunIds.retainAll(cmDefFuns);
        return defFunIds;
    }
}
